// 导入所需的 Angular 核心模块
// Directive: 用于声明这是一个指令
// ElementRef: 用于直接访问 DOM 元素
// Input: 用于接收外部传入的属性
// OnChanges, OnDestroy, OnInit: 生命周期钩子接口
// Renderer2: 用于安全地操作 DOM
// SimpleChanges: 用于检测输入属性的变化
import { Directive, ElementRef, Input, OnChanges, OnDestroy, OnInit, Renderer2, SimpleChanges } from '@angular/core';

// @Directive 装饰器声明这是一个指令
@Directive({
  // selector 定义了指令的使用方式，[appLoading] 表示这个指令可以作为属性使用
  // 例如：<div [appLoading]="true">
  selector: '[appLoading]',
  // standalone: true 表示这是一个独立指令，不需要在 NgModule 中声明
  standalone: true
})
// 实现多个生命周期接口
export class LoadingDirective implements OnInit, OnChanges, OnDestroy {
  // @Input 装饰器允许从外部传入属性值
  // appLoading: 控制加载状态的显示/隐藏
  @Input() appLoading = false;
  // loadingText: 自定义加载提示文本
  @Input() loadingText = '加载中...';

  // 存储加载遮罩层的 DOM 元素引用
  private loadingElement: HTMLElement | null = null;
  // 存储宿主元素原始的 position 样式值
  private originalPosition: string | null = null;

  // 构造函数，注入所需的服务
  constructor(
    // el: 用于访问宿主元素
    private el: ElementRef,
    // renderer: 用于安全地操作 DOM（推荐使用 renderer 而不是直接操作 DOM）
    private renderer: Renderer2
  ) {}

  // 初始化生命周期钩子
  ngOnInit() {
    // 获取宿主元素当前的 position 样式值
    this.originalPosition = getComputedStyle(this.el.nativeElement).position || null;
    // 如果宿主元素不是相对定位、绝对定位或固定定位，则设置为相对定位
    // 这是为了让加载遮罩层可以相对于宿主元素定位
    if (!['relative', 'absolute', 'fixed'].includes(this.originalPosition || '')) {
      this.renderer.setStyle(this.el.nativeElement, 'position', 'relative');
    }
  }

  // 属性变化生命周期钩子
  ngOnChanges(changes: SimpleChanges) {
    // 当 appLoading 属性发生变化时
    if (changes['appLoading']) {
      if (this.appLoading) {
        // 如果设置为 true，显示加载遮罩
        this.showLoading();
      } else {
        // 如果设置为 false，隐藏加载遮罩
        this.hideLoading();
      }
    }
  }

  // 销毁生命周期钩子
  ngOnDestroy() {
    // 移除加载遮罩
    this.hideLoading();
    // 恢复宿主元素的原始 position 值
    if (this.originalPosition !== null) {
      this.renderer.setStyle(this.el.nativeElement, 'position', this.originalPosition);
    }
  }

  // 显示加载遮罩的私有方法
  private showLoading() {
    if (!this.loadingElement) {
      // 创建加载遮罩层的容器元素
      this.loadingElement = this.renderer.createElement('div');
      this.renderer.addClass(this.loadingElement, 'loading-overlay');
      
      // 设置遮罩层的基本样式
      const styles = {
        position: 'absolute',     // 相对于宿主元素定位
        top: '0',                // 顶部对齐
        left: '0',               // 左侧对齐
        width: '100%',           // 宽度充满宿主元素
        height: '100%',          // 高度充满宿主元素
        display: 'flex',         // 使用 flex 布局
        justifyContent: 'center', // 水平居中
        alignItems: 'center',     // 垂直居中
        backgroundColor: 'rgba(255, 255, 255, 0.8)', // 半透明白色背景
        zIndex: '1000'           // 确保遮罩层在上层显示
      };

      // 应用样式到遮罩层
      Object.entries(styles).forEach(([key, value]) => {
        this.renderer.setStyle(this.loadingElement, key, value);
      });

      // 创建加载内容的容器
      const contentContainer = this.renderer.createElement('div');
      this.renderer.setStyle(contentContainer, 'text-align', 'center');

      // 创建加载动画图标
      const spinner = this.renderer.createElement('div');
      this.renderer.addClass(spinner, 'loading-spinner');
      // 设置加载图标的样式（一个旋转的圆环）
      this.renderer.setStyle(spinner, 'border', '4px solid #f3f3f3');
      this.renderer.setStyle(spinner, 'border-top', '4px solid #3498db');
      this.renderer.setStyle(spinner, 'border-radius', '50%');
      this.renderer.setStyle(spinner, 'width', '40px');
      this.renderer.setStyle(spinner, 'height', '40px');
      this.renderer.setStyle(spinner, 'animation', 'spin 1s linear infinite');
      this.renderer.setStyle(spinner, 'margin', '0 auto 8px');

      // 创建加载提示文本
      const text = this.renderer.createElement('div');
      this.renderer.setStyle(text, 'color', '#666');
      this.renderer.setStyle(text, 'font-size', '14px');
      const textContent = this.renderer.createText(this.loadingText);
      this.renderer.appendChild(text, textContent);

      // 组装加载内容（图标和文本）
      this.renderer.appendChild(contentContainer, spinner);
      this.renderer.appendChild(contentContainer, text);
      this.renderer.appendChild(this.loadingElement, contentContainer);

      // 将加载遮罩添加到宿主元素
      this.renderer.appendChild(this.el.nativeElement, this.loadingElement);

      // 添加旋转动画的关键帧样式
      const styleElement = this.renderer.createElement('style');
      const keyframes = `
        @keyframes spin {
          0% { transform: rotate(0deg); }
          100% { transform: rotate(360deg); }
        }
      `;
      const styleText = this.renderer.createText(keyframes);
      this.renderer.appendChild(styleElement, styleText);
      this.renderer.appendChild(document.head, styleElement);
    }
  }

  // 隐藏加载遮罩的私有方法
  private hideLoading() {
    if (this.loadingElement) {
      // 从 DOM 中移除加载遮罩
      this.renderer.removeChild(this.el.nativeElement, this.loadingElement);
      // 清空引用
      this.loadingElement = null;
    }
  }
}